#include "AliOSSCopyRequest.h"

#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>

#include "AliOSSAdapter.h"

namespace AliOSS
{

	AliOSSCopyRequest::AliOSSCopyRequest(
		AliOSSAdapter *parent,
		QNetworkAccessManager *networkAccessManager,
		const QString &bucket,
		const QString &accessId) 
		: QObject(parent),
		networkAccessManager(networkAccessManager),
		bucket(bucket), 
		accessId(accessId)
	{

	}

	void AliOSSCopyRequest::doCopy()
{
		QString authorization = "OSS [accessKeyId]:[signature]";
		authorization.replace("[accessKeyId]", accessId);
		authorization.replace("[signature]", signature);

		QString url = "http://[bucket].oss-cn-shenzhen.aliyuncs.com/[object]";
		url.replace("[bucket]", bucket);
		url.replace("[object]", dstPath);

		QNetworkRequest request(url);
		request.setRawHeader("Date", dtstr.toLocal8Bit());
		request.setRawHeader("Authorization", authorization.toLocal8Bit());
		for (const auto &p : _ossHeaders.toStdMap())
		{
			QString k = p.first.toLower();
			const QByteArray &v = p.second;
			request.setRawHeader(k.toUtf8(), v);
		}
// 		request.setHeader(QNetworkRequest::ContentTypeHeader, this->contentType);

        reply = networkAccessManager->put(request, QByteArray());
		reply->setParent(this); // set auto-delete action with uploader
		QObject::connect(reply, &QNetworkReply::finished, this, &AliOSSCopyRequest::onRequestFinished);
		QObject::connect(reply, &QNetworkReply::uploadProgress, this, &AliOSSCopyRequest::uploadProgress);
		QObject::connect(reply, static_cast<void(QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), this, &AliOSSCopyRequest::uploadError);

		// debug info
		QObject::connect(reply,
			static_cast<void(QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
			[this]()
		{
			qWarning().noquote() << QString("Copy Error (%1:%2) : \n%3")
				.arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt())
				.arg(reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())
				.arg(QString::fromUtf8(reply->readAll()));
		});
	}

	void AliOSSCopyRequest::setNeededInformation(const QString &datetimestr,
		const QString &signature)
	{
		this->dtstr = datetimestr;
		this->signature = signature;
	}

	void AliOSSCopyRequest::prepare(const QString &srcPath, const QString &dstPath)
	{
		this->srcPath = srcPath;
        this->dstPath = dstPath;
        this->_ossHeaders = QMap<QString, QByteArray>{ { "x-oss-copy-source", 
            QString("/%1/%2")
            .arg(this->bucket)
            .arg(srcPath)
            .toUtf8() } };
	}

	void AliOSSCopyRequest::onRequestFinished()
	{
		if (isOk())
			uploadFinished();
		else
			uploadFailed();
	}

	bool AliOSSCopyRequest::isOk()
	{
		if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200)
		{
			qWarning().noquote() << QString("Copy finished but failed (%1:%2) : \n%3")
				.arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt())
				.arg(reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString())
				.arg(QString::fromUtf8(reply->readAll()));
		}
		return reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200;
	}

}